package isp.apps.example.shoppingcart.domain.unittest;

import isp.apps.example.shoppingcart.domain.Item;
import isp.apps.example.shoppingcart.domain.SimpleShoppingCart;

import java.util.Collections;

import java.math.BigDecimal;

/**
 * The test class ShoppingCartTest.
 *
 * @author  (your name)
 * @version (a version number or a date)
 */
public class ShoppingCartTest
  extends junit.framework.TestCase
{
  private SimpleShoppingCart cart;
  private Item item;
  private Item item2;

  /**
     * Default constructor for test class ShoppingCartTest
     */
  public ShoppingCartTest()
  {
  }

  /**
     * Sets up the test fixture.
     *
     * Called before every test case method.
     */
  protected void setUp()
  {
    cart = new SimpleShoppingCart();

    item = new Item();
    item.setSku("109430957");
    item.setDescription("A good book on java");
    item.setName("Effective Java");
    item.setCost(new BigDecimal("8.00"));

    item2 = new Item();
    item2.setSku("1234512345");
    item2.setDescription("A book containing words");
    item2.setName("Webster's Dictionary");
    item2.setCost(new BigDecimal("20.00"));
  }

  /**
     * Tears down the test fixture.
     *
     * Called after every test case method.
     */
  protected void tearDown()
  {
    cart = null;
  }

  /*
     * Test adding an item - DONE
     * Test removing an item - DONE
     * Test emptying cart - DONE
     * Test item count after adding x items - DONE
     * Test adding a null item - DONE
     * Test emptying an already empty cart - DONE
     * Test removing an item twice - DONE
     * Test getting total price - DONE
     * Test getting distinct items after adding multiple items - DONE
     * Test for correct total quantity after adding multiple items - DONE
     * Test altering an existing item's quantity (esp to 0) - DONE
     * Test altering a non-existant item's quantity - DONE
     * Test retrieving item by sku - DONE
     * Add a negative quantity of an item 
     */

  public void testEmptyShoppingCartAsInitialState()
  {
    assertEquals(true, cart.isEmpty());
  }

  public void testAddingItem()
  {
    cart.addItem(item, 1);
    assertEquals(cart.getItemQuantity(item), 1);
  }

  public void testRemovingAnItem()
  {
    cart.addItem(item, 1);
    cart.removeItem(item, 1);
    assertEquals(cart.getItemQuantity(item), 0);
  }

  public void testRemovingMoreItemsThanArePresent()
  {
    cart.addItem(item, 1);
    cart.removeItem(item, 2);
    assertEquals(cart.getItemQuantity(item), 0);
  }

  public void testAddingNullItem()
  {
    cart.addItem(null, 1);
    assertEquals(cart.getItemQuantity(item), 0);
  }

  public void testRemovingAnItemWithItemsLeft()
  {
    cart.addItem(item, 2);
    cart.removeItem(item, 1);
    assertEquals(cart.getItemQuantity(item), 1);
  }

  public void testRemovingItemTwice()
  {
    cart.addItem(item);
    assertTrue(cart.removeItem(item) > cart.removeItem(item));
  }

  public void testEmptyTheCart()
  {
    cart.addItem(item, 2);
    cart.removeItem(item, 1);
    assertEquals(cart.getItemQuantity(item), 1);
  }

  public void testEmptyAlreadyEmptyCart()
  {
    cart.addItem(item, 1);
    cart.removeItem(item, 1);
    cart.emptyCart();
    assertEquals(cart.getItemQuantity(item), 0);
  }

  public void testEmptyCartTwiceInARow()
  {
    cart.addItem(item, 1);
    cart.emptyCart();
    cart.emptyCart();
    assertEquals(cart.getItemQuantity(item), 0);
  }

  public void testEmptyCartBySettingQuantityToZero()
  {
    cart.addItem(item, 2);
    cart.setItemQuantity(item.getSku(), 0);
    assertEquals(cart.getItemQuantity(item), 0);
  }

  public void testEmptyCartByDecreasingQuantity()
  {
    cart.addItem(item, 2);
    cart.removeItem(item, 2);
    assertEquals(cart.isEmpty(), false);
  }

  public void testGetCartDistinctItemCount()
  {
    cart.addItem(item, 1);
    cart.addItem(item2, 2);
    assertEquals(cart.getCartDistinctItemCount(), 2);
  }

  public void testgetCartTotalQuantityCount()
  {
    cart.addItem(item, 1);
    cart.addItem(item2, 2);
    assertEquals(cart.getCartTotalQuantityCount(), 3);
    assertEquals(cart.getItemQuantity(item), 1);
    assertEquals(cart.getItemQuantity(item2), 2);
  }

  public void testGetTotalCost()
  {
    cart.addItem(item, 1);
    cart.addItem(item2, 1);
    assertEquals(cart.getTotalPrice(), new BigDecimal("28"));
  }

  public void testGetItemBySku()
  {
    cart.addItem(item);
    Item i =
      cart.getItemBySku("109430957");
    assertEquals(i.getName(), "Effective Java");
  }

  public void testAlterNonExistingItemsQuantity()
  {
    int i = cart.setItemQuantity(item.getSku(), 10);
    assertEquals(i, 0);
  }

  public void testAddNegativeQuantity()
  {
    try
    {
      cart.addItem(item, -1);
      fail("exception expected");
    }
    catch (IllegalArgumentException expected)
    {
      assertTrue(true);
    }
  }
}
